/************************************************************************
* mapgen_noise.c
* voxelands - 3d voxel world sandbox game
* Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
************************************************************************/

#include "common.h"

#include <math.h>

static int seed = 12345;

static float noise(int x, int z)
{
	int a = (x*43695)+(z*43721)+seed;
	int b = (a>>13)^a;

	float d = ((float)(b%1000)/1000.0);


	d = (d*2.0)-1.0;

	return d;
}

static float smooth_noise(int x, int z)
{
	float sides;
	float centre;

	sides = noise(x+1,z);
	sides += noise(x-1,z);
	sides += noise(x,z+1);
	sides += noise(x,z-1);
	sides /= 8.0;

	centre = noise(x,z);
	centre /= 4.0;

	return (sides+centre);
}

static float interpolated_noise(int x, int z, float devisor)
{
	float v1;
	float v2;
	float v3;
	float v4;
	float i1;
	float i2;
	float fx = (float)x/devisor;
	float fz = (float)z/devisor;
	int ix = fx;
	int iz = fz;
	if (x<1)
		ix--;
	if (z<1)
		iz--;
	fx -= ix;
	fz -= iz;

	v1 = smooth_noise(ix,iz);
	v2 = smooth_noise(ix+1,iz);
	v3 = smooth_noise(ix,iz+1);
	v4 = smooth_noise(ix+1,iz+1);

	i1 = (v1*(1.0-fx))+(v2*fx);
	i2 = (v3*(1.0-fx))+(v4*fx);

	return (i1*(1.0-fz))+(i2*fz);
}

void mapgen_seed(int s)
{
	seed = s;
}

float noise_height(int x, int z)
{
	float n = interpolated_noise(x,z,60.0)*70.0;

	n += interpolated_noise(x,z,20.0)*20.0;
	n += interpolated_noise(x,z,10.0)*4.0;

	return n;
}
